﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Light;
using PloobsEngine.Modelo;
using PloobsEngine.SceneControl;
using PloobsEngine.Cameras;

namespace PloobsEngine.Material
{
    /// <summary>
    /// Parcial Shader
    /// Usually atached to others shaders
    /// create a fake projection shadow
    /// </summary>
    public class NormalDeferredFakeShadowParcial : ParcialShader 
    {
        private Color shadowColor = Color.Black;

        public Color ShadowColor
        {
            get { return shadowColor; }
            set { shadowColor = value; }
        }
        private float shadownAlpha = 0.3f;

        public float ShadownAlpha
        {
            get { return shadownAlpha; }
            set { shadownAlpha = value; }
        }

        private Plane ground = new Plane(0, 1, 0, 0);

        public Plane Ground
        {
            get { return ground; }
            set { ground = value; }
        }

        Effect simpleAlphaDraw;
        public override void Initialize()
        {
            base.Initialize();
            simpleAlphaDraw = EngineStuff.InternalContentManager.GetAsset<Effect>("SimpleAlphaDraw");
        }

        public override ShaderParcialFuncion ShaderParcialFuncion
        {
            get
            {
                return ShaderParcialFuncion.POS_DRAW;
            }
           
        }        

        public override void Draw(IModelo modelo, IRenderHelper render, ICamera cam, IList<ILight> lights)
        {
            if (obj == null)
                return;

            EngineStuff.GraphicsDevice.Clear(ClearOptions.Stencil, Color.Black, 0, 1);

            foreach (var item in lights.Where((a, b) => a.CastShadown == true && a.LightType == LightType.Deferred_Directional))
            {
                DirectionalLight ilight = item as DirectionalLight;
                Matrix shadow = Matrix.CreateShadow(ilight.LightDirection * -1, ground);
                Matrix MWorld = obj.getWorldMatrix() * shadow;
                Matrix[] boneTransforms = modelo.getBonesTransformation();
                
                EngineStuff.GraphicsDevice.RenderState.StencilEnable = true;
                EngineStuff.GraphicsDevice.RenderState.StencilPass = StencilOperation.Increment;
                EngineStuff.GraphicsDevice.RenderState.StencilFunction = CompareFunction.Equal;
                EngineStuff.GraphicsDevice.RenderState.ReferenceStencil = 1;

                EngineStuff.GraphicsDevice.RenderState.AlphaBlendEnable = true;
                EngineStuff.GraphicsDevice.RenderState.SourceBlend = Microsoft.Xna.Framework.Graphics.Blend.SourceAlpha;
                EngineStuff.GraphicsDevice.RenderState.DestinationBlend = Microsoft.Xna.Framework.Graphics.Blend.InverseSourceAlpha;

                
                Matrix wld = obj.getWorldMatrix();
                for (int i = 0; i < modelo.MeshNumber; i++)
                {
                    BatchInformation[] bi = modelo.GetBatchInformation(i);
                    Matrix w1 = Matrix.Multiply(wld, boneTransforms[modelo.GetParentBoneIndex(i)]);
                    simpleAlphaDraw.Parameters["World"].SetValue(w1);
                    for (int j = 0; j < bi.Count(); j++)
                    {

                        simpleAlphaDraw.Begin();                        
                        simpleAlphaDraw.Parameters["Projection"].SetValue(cam.Projection);
                        simpleAlphaDraw.Parameters["View"].SetValue(cam.View);
                        simpleAlphaDraw.Parameters["alpha"].SetValue(shadownAlpha);
                        simpleAlphaDraw.Parameters["color"].SetValue(shadowColor.ToVector3());
                        EngineStuff.GraphicsDevice.VertexDeclaration = bi[j].VertexDeclaration;
                        EngineStuff.GraphicsDevice.Vertices[0].SetSource(modelo.GetVertexBuffer(i), bi[j].StreamOffset, bi[j].VertexStride);
                        EngineStuff.GraphicsDevice.Indices = modelo.GetIndexBuffer(i);
                        this.simpleAlphaDraw.CurrentTechnique.Passes[0].Begin();
                        EngineStuff.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, bi[j].BaseVertex, 0, bi[j].NumVertices, bi[j].StartIndex, bi[j].PrimitiveCount);
                        this.simpleAlphaDraw.CurrentTechnique.Passes[0].End();
                        simpleAlphaDraw.End();
                        
                    }
                }


                EngineStuff.GraphicsDevice.RenderState.AlphaBlendEnable = false;
                EngineStuff.GraphicsDevice.RenderState.StencilEnable = false;
            }
        }   
        }
    }

